/*
BLDC电机控制
*/

#include <stdio.h>
#include "main.h"
#include "stm32g4xx_ll_tim.h"
#include "bldc.h"
#include "hall.h"
#include "pid.h"
#include "adc.h"
#include "fdcan.h"

TIM_HandleTypeDef htim1;
extern uint16_t g_adc_val[ADC_CH_NUM]; 

bldc_ctrl_t bldc_ctrl = {
    .motor_status = MOTOR_STOP,
    .motor_direction = FORWARD_ROTATION,
    .pwm_duty = 0
};


// 添加换向安全控制变量
static volatile uint8_t direction_change_pending = 0;
static volatile motor_direction_t pending_direction;
static volatile uint8_t zero_vector_cycles = 0;
#define ZERO_VECTOR_DELAY_CYCLES 3  // 零矢量延时周期数
_bldc_obj g_bldc_motor1 = {
    .run_flag = MOTOR_STOP,
    .dir = FORWARD_ROTATION,
    .initial_calibration_done = 0 /* 初始校准默认为未完成 */
};

static uint8_t last_hall_value = 0;

uint32_t motor_timer_tick = 0;


static void calculate_motor_speed(uint8_t current_hall);


/*无刷电机正反转控制逻辑表。
+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+
| 方向   | 霍尔 W | 霍尔 V | 霍尔 U | U+     | U-     | V+     | V-     | W+     | W-     | 顺序   |
+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+
|        | 1      | 0      | 1      | 打开   | 关闭   | 关闭   | 打开   | 关闭   | 关闭   | ↑      |
+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+
|        | 0      | 0      | 1      | 打开   | 关闭   | 关闭   | 关闭   | 关闭   | 打开   | ↑      |
+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+
| 正转   | 0      | 1      | 1      | 关闭   | 关闭   | 打开   | 关闭   | 关闭   | 打开   | ↑      |
+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+
|        | 0      | 1      | 0      | 关闭   | 打开   | 打开   | 关闭   | 关闭   | 关闭   | ↑      |
+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+
|        | 1      | 1      | 0      | 关闭   | 打开   | 关闭   | 关闭   | 打开   | 关闭   | ↑      |
+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+
|        | 1      | 0      | 0      | 关闭   | 关闭   | 关闭   | 打开   | 打开   | 关闭   | ↑      |
+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+
|--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------|
|        | 1      | 0      | 1      | 关闭   | 打开   | 打开   | 关闭   | 关闭   | 关闭   | ↓      |
+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+
|        | 0      | 0      | 1      | 关闭   | 打开   | 关闭   | 关闭   | 打开   | 关闭   | ↓      |
+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+
| 反转   | 0      | 1      | 1      | 关闭   | 关闭   | 关闭   | 打开   | 打开   | 关闭   | ↓      |
+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+
|        | 0      | 1      | 0      | 打开   | 关闭   | 关闭   | 打开   | 关闭   | 关闭   | ↓      |
+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+
|        | 1      | 1      | 0      | 关闭   | 关闭   | 关闭   | 关闭   | 关闭   | 打开   | ↓      |
+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+
|        | 1      | 0      | 0      | 关闭   | 关闭   | 打开   | 关闭   | 关闭   | 打开   | ↓      |
+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+
*/

/*  六步换向函数指针数组 ,这个数组的函数顺序不是乱排的，它是根据电机正反转控制逻辑表来排的*/
//正转 4、6、2、3、1、5
motor_ctr_t pfunclist_m1[6] =
{
    &m1_uhwl, &m1_vhul, &m1_vhwl,
    &m1_whvl, &m1_uhvl, &m1_whul
};

/* bldc 电机初始化 */
void bldc_init(void)
{
    GPIO_InitTypeDef GPIO_InitStruct = {0};

      /* GPIO Ports Clock Enable */
    __HAL_RCC_GPIOC_CLK_ENABLE();

    //拉低，不允许输出
    HAL_GPIO_WritePin(GPIOC, MOTOR_OUTPUT_ENABLE_PIN, GPIO_PIN_RESET);
     /*Configure GPIO pin : PC13 */
    GPIO_InitStruct.Pin = MOTOR_OUTPUT_ENABLE_PIN;
    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);

    // 初始化定时器
    bldc_timer_init();
    
    // 初始化TIM2输入捕获测速
    hall_init();

    // 在启动前执行初始电流校准
    printf("Performing initial current offset calibration...\r\n");
    bldc_current_offset_calibration();
}

/* 定时器PWM初始化 */
void bldc_timer_init(void)
{
    GPIO_InitTypeDef GPIO_InitStruct = {0};
    TIM_OC_InitTypeDef sConfigOC = {0};
    TIM_BreakDeadTimeConfigTypeDef sBreakDeadTimeConfig = {0};
    
    // 使能时钟
    __HAL_RCC_GPIOA_CLK_ENABLE();
    __HAL_RCC_GPIOB_CLK_ENABLE();
    __HAL_RCC_TIM1_CLK_ENABLE();
    
    // 配置PWM输出引脚 (上桥臂)
    GPIO_InitStruct.Pin = MOTOR_U_UP_PIN|MOTOR_V_UP_PIN|MOTOR_W_UP_PIN;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF6_TIM1;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
    
    // 配置互补PWM输出引脚 (下桥臂)
    GPIO_InitStruct.Pin = MOTOR_U_LOW_PIN|MOTOR_V_LOW_PIN;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF6_TIM1;
    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);


    // 配置互补PWM输出引脚 (下桥臂)
    //#NOTE 需要非常注意复用是 GPIO_AF4_TIM1， 这个要查询datasheet 的Alternate function表格
    GPIO_InitStruct.Pin = MOTOR_W_LOW_PIN;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF4_TIM1;  //-----注意这里
    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); // 初始化GPIOB
    
    // 定时器基本配置，pwm 周期为PWM_FREQUENCY_HZ 20k
    htim1.Instance = TIM1;
    htim1.Init.Prescaler = 0;  // 不分频，使用系统时钟
    htim1.Init.CounterMode = TIM_COUNTERMODE_UP;
    htim1.Init.Period = GET_PWM_PERIOD_VALUE() - 1;  // PWM周期，20k 根据时钟动态计算
    htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
    htim1.Init.RepetitionCounter = TIMER_REPETITION_COUNT-1;  // 重复计数器，每TIMER_REPETITION_COUNT个PWM周期产生一次更新中断，提高响应频率到2kHz
    htim1.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE;

    
    if (HAL_TIM_PWM_Init(&htim1) != HAL_OK)
    {
        Error_Handler();
    }
    
    sConfigOC.OCMode = TIM_OCMODE_PWM1;         // 设置输出比较模式为PWM模式1。
    sConfigOC.Pulse = 0;                        // 设置比较值（占空比）的初始值为0。
    sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH; // 设置主输出的有效电平极性为高电平。
    // 设置互补输出的有效电平极性也为高电平，当OCPolarity为ON,则它为OFF,当OCPolarity为OFF,则它为ON,这里设置的是
    //它为ON时的电平，所以这个是正确的，它也是TIM_OCNPOLARITY_HIGH
    sConfigOC.OCNPolarity = TIM_OCNPOLARITY_HIGH; 
    sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;  // 禁用快速模式，通常情况下不需要开启。
    sConfigOC.OCIdleState = TIM_OCIDLESTATE_RESET; // 设置定时器在空闲模式（如停止或刹车）时，主输出引脚强制为低电平（RESET）。
    sConfigOC.OCNIdleState = TIM_OCNIDLESTATE_RESET; // 设置定时器在空闲模式时，互补输出引脚也强制为低电平（RESET）。
    
    if (HAL_TIM_PWM_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_1) != HAL_OK)
    {
        Error_Handler();
    }
    
    // 配置PWM通道2 (V相)
    if (HAL_TIM_PWM_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_2) != HAL_OK)
    {
        Error_Handler();
    }
    
    // 配置PWM通道3 (W相)
    if (HAL_TIM_PWM_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_3) != HAL_OK)
    {
        Error_Handler();
    }
    printf("pwm Period: %d,pwm Duty: %d\r\n", htim1.Init.Period, sConfigOC.Pulse);
    
    // 配置死区时间和刹车功能
    sBreakDeadTimeConfig.OffStateRunMode = TIM_OSSR_DISABLE;      // 运行模式下关断状态：立即设为非活动状态
    sBreakDeadTimeConfig.OffStateIDLEMode = TIM_OSSI_DISABLE;     // 空闲模式下关断状态：立即设为非活动状态  
    sBreakDeadTimeConfig.LockLevel = TIM_LOCKLEVEL_1;             // 锁定级别1：防止意外修改死区时间等关键参数
    sBreakDeadTimeConfig.DeadTime = (uint32_t)(GET_TIM1_CLOCK_FREQ() / 1000000000.0f * DEAD_TIME_NS); // 死区时间：根据配置和时钟动态计算
    sBreakDeadTimeConfig.BreakState = TIM_BREAK_DISABLE;           // 不启用刹车1：提供硬件级安全保护
    sBreakDeadTimeConfig.BreakPolarity = TIM_BREAKPOLARITY_HIGH;  // 刹车1极性：高电平有效
    sBreakDeadTimeConfig.BreakFilter = 3;                         // 刹车1滤波：防止噪声误触发
    sBreakDeadTimeConfig.Break2State = TIM_BREAK_DISABLE;         // 不启用刹车2
    sBreakDeadTimeConfig.Break2Polarity = TIM_BREAK2POLARITY_HIGH; // 刹车2极性：高电平有效
    sBreakDeadTimeConfig.Break2Filter = 3;                        // 刹车2滤波：3级滤波，防止噪声误触发
    sBreakDeadTimeConfig.AutomaticOutput = TIM_AUTOMATICOUTPUT_DISABLE; // 禁用自动输出恢复：需要软件手动恢复
    
    if (HAL_TIMEx_ConfigBreakDeadTime(&htim1, &sBreakDeadTimeConfig) != HAL_OK)
    {
        Error_Handler();
    }     
    // #NOTEEnable (CCxE, CCxNE and OCxM) preload,它是实现同步配置输出的关键。
    LL_TIM_CC_EnablePreload(TIM1);
    // 配置NVIC中断优先级
    HAL_NVIC_SetPriority(TIM1_UP_TIM16_IRQn, 2, 0);
}




/**
  * @brief  U相上桥臂导通，V相下桥臂导通
  * @param  无
  * @retval 无
  */
void m1_uhvl(void)
{
    // --- W 相: 高阻态 --- 禁用 W 相输出
    TIM1->CCER &= ~(TIM_CCER_CC3E | TIM_CCER_CC3NE);

    // --- U 相: PWM 输出 ---
    TIM1->CCMR1 &= ~(TIM_CCMR1_OC1M_Msk); // 清除 U 相 (CH1) 的输出比较模式位
    TIM1->CCMR1 |= (6U << TIM_CCMR1_OC1M_Pos); // 设置为 PWM1 模式 (0b110)
    // TIM1->CCR1 =  g_bldc_motor1.pwm_duty ;
    TIM1->CCER |= (TIM_CCER_CC1E | TIM_CCER_CC1NE);

    // --- V 相: 强制非活动电平 ---
    TIM1->CCMR1 &= ~(TIM_CCMR1_OC2M_Msk); // 1. 清除 V 相 (CH2) 的输出比较模式位
    TIM1->CCMR1 |= (4U << TIM_CCMR1_OC2M_Pos); // 2. 设置 V 相 (CH2) 为 "Force Inactive" 模式 (0b100)
    TIM1->CCER |= (TIM_CCER_CC2E | TIM_CCER_CC2NE);// 3. 使能 V 相输出，让强制电平生效
}

/**
  * @brief  U相上桥臂导通，W相下桥臂导通
  * @param  无
  * @retval 无
  */
void m1_uhwl(void)
{
    // --- V 相: 高阻态 ---
    TIM1->CCER &= ~(TIM_CCER_CC2E | TIM_CCER_CC2NE); // 禁用 V 相输出

    // --- U 相: PWM 输出 ---
    TIM1->CCMR1 &= ~(TIM_CCMR1_OC1M_Msk); // 清除 U 相 (CH1) 的输出比较模式位
    TIM1->CCMR1 |= (6U << TIM_CCMR1_OC1M_Pos); // 设置为 PWM1 模式 (0b110)
    // TIM1->CCR1 =  g_bldc_motor1.pwm_duty ;
    TIM1->CCER |= (TIM_CCER_CC1E | TIM_CCER_CC1NE);

    // --- W 相: 强制非活动电平 ---
    TIM1->CCMR2 &= ~(TIM_CCMR2_OC3M_Msk); // 清除 W 相 (CH3) 的输出比较模式位
    TIM1->CCMR2 |= (4U << TIM_CCMR2_OC3M_Pos); // 设置 W 相 (CH3) 为 "Force Inactive" 模式 (0b100)
    TIM1->CCER |= (TIM_CCER_CC3E | TIM_CCER_CC3NE); // 使能 W 相输出，让强制电平生效
}

/**
  * @brief  V相上桥臂导通，W相下桥臂导通
  * @param  无
  * @retval 无
  */
void m1_vhwl(void)
{
        // --- U 相: 高阻态 ---
    TIM1->CCER &= ~(TIM_CCER_CC1E | TIM_CCER_CC1NE); // 禁用 U 相输出

    // --- V 相: PWM 输出 ---
    TIM1->CCMR1 &= ~(TIM_CCMR1_OC2M_Msk); // 清除 V 相 (CH2) 的输出比较模式位
    TIM1->CCMR1 |= (6U << TIM_CCMR1_OC2M_Pos); // 设置为 PWM1 模式 (0b110)
    // TIM1->CCR2 =  g_bldc_motor1.pwm_duty ;
    TIM1->CCER |= (TIM_CCER_CC2E | TIM_CCER_CC2NE);

    // --- W 相: 强制非活动电平 ---
    TIM1->CCMR2 &= ~(TIM_CCMR2_OC3M_Msk); // 清除 W 相 (CH3) 的输出比较模式位
    TIM1->CCMR2 |= (4U << TIM_CCMR2_OC3M_Pos); // 设置 W 相 (CH3) 为 "Force Inactive" 模式 (0b100)
    TIM1->CCER |= (TIM_CCER_CC3E | TIM_CCER_CC3NE); // 使能 W 相输出，让强制电平生效

}

/**
  * @brief  V相上桥臂导通，U相下桥臂导通
  * @param  无
  * @retval 无
  */
void m1_vhul(void)
{
       // --- W 相: 高阻态 ---
    TIM1->CCER &= ~(TIM_CCER_CC3E | TIM_CCER_CC3NE); // 禁用 W 相输出

    // 设置 V 相 (CH2) 为 PWM1 模式
    TIM1->CCMR1 &= ~(TIM_CCMR1_OC2M_Msk); // 清除 V 相 (CH2) 的输出比较模式位
    TIM1->CCMR1 |= (6U << TIM_CCMR1_OC2M_Pos); // 设置为 PWM1 模式 (0b110)
    // TIM1->CCR2 =  g_bldc_motor1.pwm_duty ;
    TIM1->CCER |= (TIM_CCER_CC2E | TIM_CCER_CC2NE);

    // --- U 相: 强制非活动电平 ---
    TIM1->CCMR1 &= ~(TIM_CCMR1_OC1M_Msk); // 清除 U 相 (CH1) 的输出比较模式位
    TIM1->CCMR1 |= (4U << TIM_CCMR1_OC1M_Pos); // 设置 U 相 (CH1) 为 "Force Inactive" 模式 (0b100)
    TIM1->CCER |= (TIM_CCER_CC1E | TIM_CCER_CC1NE); // 使能 U 相输出，让强制电平生效
}

/**
  * @brief  W相上桥臂导通，U相下桥臂导通
  * @param  无
  * @retval 无
  */
void m1_whul(void)
{
        // --- V 相: 高阻态 ---
    TIM1->CCER &= ~(TIM_CCER_CC2E | TIM_CCER_CC2NE); // 禁用 V 相输出

    // --- W 相: PWM 输出 ---
    TIM1->CCMR2 &= ~(TIM_CCMR2_OC3M_Msk); // 清除 W 相 (CH3) 的输出比较模式位
    TIM1->CCMR2 |= (6U << TIM_CCMR2_OC3M_Pos); // 设置为 PWM1 模式 (0b110)
    // TIM1->CCR3 =  g_bldc_motor1.pwm_duty ;
    TIM1->CCER |= (TIM_CCER_CC3E | TIM_CCER_CC3NE);

    // --- U 相: 强制非活动电平 ---
    TIM1->CCMR1 &= ~(TIM_CCMR1_OC1M_Msk); // 清除 U 相 (CH1) 的输出比较模式位
    TIM1->CCMR1 |= (4U << TIM_CCMR1_OC1M_Pos); // 设置 U 相 (CH1) 为 "Force Inactive" 模式 (0b100)
    TIM1->CCER |= (TIM_CCER_CC1E | TIM_CCER_CC1NE); // 使能 U 相输出，让强制电平生效

}

/**
  * @brief  W相上桥臂导通，V相下桥臂导通
  * @param  无
  * @retval 无
  */
void m1_whvl(void)
{
        // --- U 相: 高阻态 ---
    TIM1->CCER &= ~(TIM_CCER_CC1E | TIM_CCER_CC1NE); // 禁用 U 相输出
    // --- W 相: PWM 输出 ---
    TIM1->CCMR2 &= ~(TIM_CCMR2_OC3M_Msk); // 清除 W 相 (CH3) 的输出比较模式位
    TIM1->CCMR2 |= (6U << TIM_CCMR2_OC3M_Pos); // 设置为 PWM1 模式 (0b110)
    //  TIM1->CCR3 =  g_bldc_motor1.pwm_duty ;
    TIM1->CCER |= (TIM_CCER_CC3E | TIM_CCER_CC3NE);

    // --- V 相: 强制非活动电平 ---
    TIM1->CCMR1 &= ~(TIM_CCMR1_OC2M_Msk); // 清除 V 相 (CH2) 的输出比较模式位
    TIM1->CCMR1 |= (4U << TIM_CCMR1_OC2M_Pos); // 设置 V 相 (CH2) 为 "Force Inactive" 模式 (0b100)
    TIM1->CCER |= (TIM_CCER_CC2E | TIM_CCER_CC2NE); // 使能 V 相输出，让强制电平生效

}

/* TIM1中断使能函数 */
void bldc_enable_timer_interrupt(void)
{
    // 使能TIM1更新中断
    __HAL_TIM_ENABLE_IT(&htim1, TIM_IT_UPDATE);
    
    HAL_NVIC_EnableIRQ(TIM1_UP_TIM16_IRQn);
    
    printf("TIM1 interrupt enabled\r\n");
}

/* TIM1中断禁用函数 */
void bldc_disable_timer_interrupt(void)
{
    // 禁用TIM1更新中断
    __HAL_TIM_DISABLE_IT(&htim1, TIM_IT_UPDATE);
    
    // 禁用NVIC中断
    HAL_NVIC_DisableIRQ(TIM1_UP_TIM16_IRQn);
    
    printf("TIM1 interrupt disabled\r\n");
}

/* 启动PWM输出 */
void bldc_start(void)
{
    // 安全检查: 确保初始校准已完成
    if (g_bldc_motor1.initial_calibration_done == 0)
    {
        printf("ERROR: Motor start failed. Initial current calibration is not complete.\r\n");
        while(g_bldc_motor1.initial_calibration_done == 0)
        {
            HAL_Delay(10);
        }
        printf("Initial current calibration completed. Starting motor...\r\n");
    }

        //最后一次hall 设置为0，一个无效值，这样在start时current_hall!=last_hall_value，
    //会触发一次换相操作，之后last_hall_value=current_hall，一切就开始了。   
    last_hall_value = 0;
    pid_inter_data_reset();

    // 启动TIM2输入捕获测速
    bldc_speed_capture_start();
    
    // 拉高，允许输出
    HAL_GPIO_WritePin(MOTOR_OUTPUT_ENABLE_PORT, MOTOR_OUTPUT_ENABLE_PIN, GPIO_PIN_SET);   
    
    
    // 启动PWM通道1及其互补输出
    if (HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1) != HAL_OK)
    {
        Error_Handler();
    }
    if (HAL_TIMEx_PWMN_Start(&htim1, TIM_CHANNEL_1) != HAL_OK)
    {
        Error_Handler();
    }
    
    // 启动PWM通道2及其互补输出
    if (HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_2) != HAL_OK)
    {
        Error_Handler();
    }
    if (HAL_TIMEx_PWMN_Start(&htim1, TIM_CHANNEL_2) != HAL_OK)
    {
        Error_Handler();
    }
    
    // 启动PWM通道3及其互补输出
    if (HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_3) != HAL_OK)
    {
        Error_Handler();
    }
    if (HAL_TIMEx_PWMN_Start(&htim1, TIM_CHANNEL_3) != HAL_OK)
    {
        Error_Handler();
    }
    g_bldc_motor1.run_flag = MOTOR_RUN;
    // 使能定时器中断
    bldc_enable_timer_interrupt();
}

void bldc_stop(void)
{
    uint8_t hall_value = 0;
    bldc_disable_timer_interrupt();
    
    // 停止TIM2输入捕获测速
    bldc_speed_capture_stop();
    
    // 拉低，不允许输出
    HAL_GPIO_WritePin(MOTOR_OUTPUT_ENABLE_PORT, MOTOR_OUTPUT_ENABLE_PIN, GPIO_PIN_RESET);
    
    // 立即清零CCR寄存器的预装载值
    htim1.Instance->CCR1 = 0;
    htim1.Instance->CCR2 = 0;
    htim1.Instance->CCR3 = 0;
    
    
    // 停止PWM输出及其互补输出
    HAL_TIM_PWM_Stop(&htim1, TIM_CHANNEL_1);
    HAL_TIMEx_PWMN_Stop(&htim1, TIM_CHANNEL_1);
    HAL_TIM_PWM_Stop(&htim1, TIM_CHANNEL_2);
    HAL_TIMEx_PWMN_Stop(&htim1, TIM_CHANNEL_2);
    HAL_TIM_PWM_Stop(&htim1, TIM_CHANNEL_3);
    HAL_TIMEx_PWMN_Stop(&htim1, TIM_CHANNEL_3);

    // #NOTE强制产生更新事件，立即将CCR预装载值传输到实际比较寄存器，否则就很有可能产生一种情况
    //就是timer stop时CCR1设置为0了，但实际它还没更新到实际比较器，在start 后会跑到一个更新事件
    //才更新，导致在start时，PWM输出不是0占空比，导致上下臂直通，烧电机
    TIM1->EGR = TIM_EGR_COMG | TIM_EGR_UG;
    // 等待更新事件完成
    while(!(htim1.Instance->SR & TIM_SR_UIF));
    htim1.Instance->SR &= ~TIM_SR_UIF;  // 清除更新中断标志
    
    //motor 本身变量 reset
    g_bldc_motor1.run_flag = MOTOR_STOP;
    g_bldc_motor1.speed = 0;
    g_bldc_motor1.pwm_duty = 0;

    //测速 计算相关变量 reset
    motor_timer_tick = 0;

    pid_init();//init 也是reset
    pid_inter_data_reset();
    fdcan_clear_direction_change_request();
    
    //debug
    hall_value = read_hall_sensors();
    printf("bldc_stop,hall: %d\r\n",hall_value);

    // // 在电机完全停止后执行重新校准
    // printf("Performing current offset re-calibration...\r\n");
    // bldc_current_offset_calibration();
}




void bldc_set_pwm_duty(uint32_t duty)
{
    if(duty > 6000)
    {
        duty = 6000;
        printf("duty > 6000, set duty to 6000\r\n");
    }
    g_bldc_motor1.pwm_duty = duty;
    printf("duty: ----%d\r\n", duty);
}

void bldc_set_motor_direction(motor_direction_t direction)
{
    if(direction == FORWARD_ROTATION || direction == REVERSE_ROTATION)
    {
        g_bldc_motor1.dir= direction;
        // printf("d:%d\r\n", direction);
    }
    else
    {
        printf("direction error: ---- %d\r\n", direction);
    }
}

uint8_t bldc_get_motor_direction(void)
{
    return g_bldc_motor1.dir;
}

uint8_t bldc_get_motor_status(void)
{
    return g_bldc_motor1.run_flag;
}

/* 调试函数：打印时钟信息 */
void bldc_print_clock_info(void)
{
    uint32_t hclk_freq = HAL_RCC_GetHCLKFreq();
    uint32_t pclk2_freq = HAL_RCC_GetPCLK2Freq();
    uint32_t tim1_clock = GET_TIM1_CLOCK_FREQ();
    uint32_t pwm_period = GET_PWM_PERIOD_VALUE();
    uint32_t actual_pwm_freq = tim1_clock / pwm_period;
    
    printf("=== clock info ===\r\n");
    printf("HCLK frequency: %u Hz\r\n", hclk_freq);
    printf("PCLK2 frequency: %u Hz\r\n", pclk2_freq);
    printf("TIM1 clock frequency: %u Hz\r\n", tim1_clock);
    printf("PWM period value(ARR): %u\r\n", pwm_period);
    printf("actual PWM frequency: %u Hz\r\n", actual_pwm_freq);
    printf("target PWM frequency: %d Hz\r\n", PWM_FREQUENCY_HZ);
    printf("RPM_CALC_CONSTANT: %llu\r\n", RPM_CALC_CONSTANT);
    printf("=====================\r\n");
}

//100us 执行一次
void bldc_timer_interrupt_callback(void)
{ 
    int32_t pid_duty = 0;
    // 更新系统滴答计数
    
    
    uint8_t current_hall = read_hall_sensors();
    
    if(current_hall == 0b000 || current_hall == 0b111)
    {     
        printf("hall not valid %d",current_hall);
        return;
    }

    if(motor_timer_tick % 32 == 0)
    {
        bldc_get_motor_rpm_from_capture();
        
        
        motor_direction_t new_direction;
        uint32_t new_speed;
        // 检查是否有反转的命令，要反转需要速度降到100以下，之后再切换方向反转
        if (fdcan_get_direction_change_request(&new_direction, &new_speed))
        {
            // 检查速度是否已经足够低
            if (g_bldc_motor1.speed <= 100)
            {
                pid_reset_integral();  // 清除PID积分误差
                bldc_set_motor_direction(new_direction);  // 设置新方向
                pid_set_target_value(new_speed);  // 设置新速度
                fdcan_clear_direction_change_request();  // 清除切换请求
                // printf("Direction changed to %d, new speed: %d\r\n", new_direction, new_speed);
            }
        }
        
        pid_duty = pid_ctrl(&g_speed_pid, g_bldc_motor1.speed);
        g_bldc_motor1.pwm_duty = pid_duty;
        
        TIM1->CCR1 =  g_bldc_motor1.pwm_duty ;
        TIM1->CCR2 =  g_bldc_motor1.pwm_duty ;
        TIM1->CCR3 =  g_bldc_motor1.pwm_duty ;
        // printf("%d\t",g_bldc_motor1.pwm_duty);
        bldc_get_phase_currents(&g_bldc_motor1.current_u, &g_bldc_motor1.current_v, &g_bldc_motor1.current_w);
    }

    if(current_hall!=last_hall_value)
    {
        // printf("hall: %d\r\n",current_hall);
        if( g_bldc_motor1.dir== FORWARD_ROTATION)
        {
            pfunclist_m1[current_hall-1]();// 正转 4、6、2、3、1、5
        }
        else
        {
            pfunclist_m1[6-current_hall](); // 反转
        }
        LL_TIM_GenerateEvent_COM(TIM1);// 产生更新事件，同时更新改变的几个寄存器
        last_hall_value = current_hall;
    }
    motor_timer_tick++;

}


/**
  * @brief  对三相电流进行零点偏置校准
  * @note   此函数应在电机完全静止时调用.
  *         它会采样多次ADC读数并计算平均值作为零点偏置.
  *         如果在此过程中电机启动, 校准会自动中止.
  * @param  无
  * @retval 无
  */
void bldc_current_offset_calibration(void)
{
    uint32_t i;
    uint32_t offset_sum_u = 0;
    uint32_t offset_sum_v = 0;
    uint32_t offset_sum_w = 0;

    // 确保在进入校准前，状态为停止
    if (g_bldc_motor1.run_flag != MOTOR_STOP)
    {
        printf("ERROR: Cannot calibrate while motor is running.\r\n");
        return;
    }

    for (i = 0; i < CURRENT_OFFSET_CALIBRATION_SAMPLES; i++)
    {
        // 检查电机是否在中途启动
        if (g_bldc_motor1.run_flag != MOTOR_STOP)
        {
            printf("WARNING: Calibration aborted due to motor start request.\r\n");
            return; // 中止校准，保留旧的偏置值
        }

        // 累加ADC读数
        // g_adc_val 是在DMA中断中被更新的，包含了经过初步平均的值
        offset_sum_u += g_adc_val[2]; // U相电流在ADC数组中的索引是2
        offset_sum_v += g_adc_val[3]; // V相电流在ADC数组中的索引是3
        offset_sum_w += g_adc_val[4]; // W相电流在ADC数组中的索引是4
        
        HAL_Delay(1); // 等待下一次DMA转换和平均计算完成
    }

    // 计算平均值并存储
    g_bldc_motor1.adc_offset_u = offset_sum_u / CURRENT_OFFSET_CALIBRATION_SAMPLES;
    g_bldc_motor1.adc_offset_v = offset_sum_v / CURRENT_OFFSET_CALIBRATION_SAMPLES;
    g_bldc_motor1.adc_offset_w = offset_sum_w / CURRENT_OFFSET_CALIBRATION_SAMPLES;

    // 标记初始校准已成功完成
    if (g_bldc_motor1.initial_calibration_done == 0)
    {
        g_bldc_motor1.initial_calibration_done = 1;
    }

    printf("Calibration complete. Offsets: U=%d, V=%d, W=%d\r\n",
           g_bldc_motor1.adc_offset_u,
           g_bldc_motor1.adc_offset_v,
           g_bldc_motor1.adc_offset_w);
}

/**
  * @brief  获取经过零点校准后的三相电流值
  * @param  i_u: 指向U相电流值(A)存储位置的指针
  * @param  i_v: 指向V相电流值(A)存储位置的指针
  * @param  i_w: 指向W相电流值(A)存储位置的指针
  * @retval 无
  */
void bldc_get_phase_currents(volatile float *i_u, volatile float *i_v, volatile float *i_w)
{
    int16_t corrected_adc_u;
    int16_t corrected_adc_v;
    int16_t corrected_adc_w;

    // 读取瞬时ADC值
    // g_adc_val 数组由 adc.c 中的DMA中断回调函数持续更新
    uint16_t raw_adc_u = g_adc_val[2];
    uint16_t raw_adc_v = g_adc_val[3];
    uint16_t raw_adc_w = g_adc_val[4];

    // 减去偏置值
    corrected_adc_u = raw_adc_u - g_bldc_motor1.adc_offset_u;
    corrected_adc_v = raw_adc_v - g_bldc_motor1.adc_offset_v;
    corrected_adc_w = raw_adc_w - g_bldc_motor1.adc_offset_w;

    // 转换为实际电流值 (Ampere)
    if (i_u) *i_u = (float)corrected_adc_u * ADC2CURT;
    if (i_v) *i_v = (float)corrected_adc_v * ADC2CURT;
    if (i_w) *i_w = (float)corrected_adc_w * ADC2CURT;
}





